#!usr/lib/python
# -*-coding:gb2312 -*-
'''
Created on 2012-11-12

@author: JeffXun
'''

import time
import socket
import select
import traceback
import threading
import pyamf.amf3 as amf


import utils.MEvent as MEvent
from  utils.NetEvent import NetEvent



class TCPServer(MEvent.IEvent):
    """ """
    socket_type        = socket.SOCK_STREAM
    socket_ip          = socket.AF_INET
    socket_re_use      = True
    socket_timeout     = 1 # seconds
    socket_listen      = 5
    socket_select_tm   = 1  #seconds
    socket_recv_len    = 2
    server_running     = False
    
    def __init__(self,address=None):
        MEvent.IEvent.__init__(self)
        self.sock    = socket.socket(TCPServer.socket_ip,TCPServer.socket_type)
        if address:
            self.address = address
        self.sockList = _SocketList()
        self.recvThread = threading.Thread(target=self._server_select,args=())
        
    def server_stop(self,status=0):
        """ """
        TCPServer.server_running = False
        self.sock.close()
        
    def server_start(self,address=None):
        """ """
        if  address:
            self.address = address
        self._server_bind()
        self._server_active()
        TCPServer.server_running = True
        self.addEventListoner(NetEvent.SOCKET_CONNECT,self._sock_connect)
        server_thread = threading.Thread(target=self._server_wait,args=())
        server_thread.start()
        
    def _server_wait(self,*args):
        """ """
        while TCPServer.server_running:
            try:
                sock,client_addr = self.sock.accept()
                evt            = NetEvent(NetEvent.SOCKET_CONNECT)
                evt.sock       = sock
                evt.address    = client_addr;
                self.dispatch(evt)
            except socket.timeout:
                continue
            except KeyboardInterrupt:
                TCPServer.server_running = False
                break
            except:
                print traceback.format_exc()
        TCPServer.server_running = False
        
        
    def _sock_connect(self,evt):
        """ """
        self.sockList.append(evt.sock, evt.address)
        print "connect:%s,%s"%(str(evt.address),evt.sock)
        if not self.recvThread.isAlive():
            self.recvThread.start()
        
    def client_Start(self,address=None):
        """ client connect to server"""
        if  address:
            self.address = address
        self._client_active()
        evt            = NetEvent(NetEvent.SOCKET_CONNECT)
        evt.sock       = self.sock
        evt.address    = self.address;
        self.dispatch(evt)
        return self.sock
        
    def _server_bind(self):
        """ socket bind"""
        if TCPServer.socket_re_use: 
            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind(self.address)
        self.sock.settimeout(TCPServer.socket_timeout)
    def _server_active(self):
        """ socket listen"""
        self.sock.listen(TCPServer.socket_listen)
    def _client_active(self):
        """ socket connect """
        self.sock.connect(self.address)
        self.sock.settimeout(TCPServer.socket_timeout)
        #self.sockList.append(self.sock, self.address) 
        
    def _server_select(self,*args):
        """ """
        while TCPServer.server_running:
            sock_list = self.sockList.getList()
            if len(sock_list) <=0:
                time.sleep(TCPServer.socket_timeout)
                continue
            try:
                rbuf,wbuf,ebuf = select.select(sock_list,[],[],TCPServer.socket_select_tm)
                if rbuf:
                    for sock in rbuf:
                        self._recv_data(sock)
            except socket.error:
                print traceback.format_exc()
            except :
                print traceback.format_exc()
          
        self._server_close()
        
    def _recv_data(self,sock):
        """ """
        try:
            ipdata = amf.ByteArray(sock.recv(TCPServer.socket_recv_len))
            ipdata.endian = ipdata.ENDIAN_LITTLE
            if len(ipdata)<2:
                self.remoceClientSock(sock)
                return
            nlen = ipdata.readShort()
            rdata = ""
            needLen = nlen-TCPServer.socket_recv_len;
            while True:
                rdata += sock.recv(needLen)
                if needLen>=0 and len(rdata)==needLen:
                    evt = NetEvent(NetEvent.SOCKET_READDATA)
                    evt.data = rdata
                    evt.sock = sock
                    self.dispatch(evt)
                    break
                else:
                    needLen = nlen-TCPServer.socket_recv_len- len(rdata)
                    time.sleep(0.5)
        except EOFError:
            self.remoceClientSock(sock)
        except socket.error:
            self.remoceClientSock(sock)
        except:
            print traceback.format_exc()
            self.remoceClientSock(sock)
            
    def _server_close(self):
        """ """
        evt = NetEvent(NetEvent.SOCKET_CLOSED)
        self.dispatch(evt)
    
    def remoceClientSock(self,sock):
        """ """
        evt = NetEvent(NetEvent.SOCKET_CLIENT_LEAVE)
        evt.sock = sock
        self.dispatch(evt)
        self.sockList.remove(sock)
    
    def __del__(self):
        """ """
        try:
            self.sock.close()
            self.sock = None
        except:
            print traceback.format_exc()
        self.sockList = None
        
class _SocketList(object):
    """ """
    def __init__(self):
        """ """
        self._socketList = {}
    def append(self,sock,address):
        """ Add socket to list """
        if self._socketList.has_key(sock):
            self._socketList[sock] = address
            print "waring,socket has a same"
        else:
            self._socketList[sock] = address
    def getList(self):
        """ return socket list """
        #socks = self._socketList.keys()
        #for i in socks:
        #    try:
        #        i.type; 
        #    except:
        #        self.remove(i)
        return self._socketList.keys()
    def getAddress(self,sock):
        """ """
        if self._socketList.has_key(sock):
            return self._socketList[sock]
        else:
            return "has not sock,address "
    def remove(self,sock):
        """ """
        if self._socketList.has_key(sock):
            res= self._socketList[sock]
            del self._socketList[sock]
            return res
        else:
            print "waring remove not exsit sock"
            return None

if __name__ == "__main__":
    s =TCPServer()
    s.server_start(("",8081))
